package handler;

import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.text.ParseException;
import java.util.Date;
import java.util.List;
import java.util.Objects;

import javax.naming.NamingException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.jsp.JspFactory;
import javax.servlet.jsp.PageContext;

import bean.Contact;
import bean.Group;
import bean.Page;
import dao.ContactDAO;
import dao.GroupDAO;
import dao.impl.ContactDAOImpl;
import dao.impl.GroupDAOImpl;
import jdbc.ContactsConnection;
import tool.ObjectConverter;

public class ContactHandler extends HttpServlet {
    private static final long serialVersionUID = -6546886680327346132L;
    private Connection conn;
    private static final String URL = "contact-handler?operate=list-contacts";
    private GroupDAO groupDAO;
    private ContactDAO contactDAO;
    private PageContext pageContext;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        StringBuilder urlBuilder = new StringBuilder(URL);
        String operate = req.getParameter("operate");
        try {
            Contact temporary = null;
            int size = ObjectConverter.parseStringToInteger(req.getParameter("size"));
            int serial = ObjectConverter.parseStringToInteger(req.getParameter("serial"));
            if (Objects.nonNull(operate) && operate.length() > 0) {
                switch (operate) {
                case "list-contacts":
                    int length;
                    String contactName = req.getParameter("contact-name");
                    if (Objects.nonNull(contactName) && (length = contactName.length()) > 0
                            && length <= Contact.MAX_CONTACT_NAME_LENGTH) {
                        urlBuilder.append("&contact-name=" + contactName);
                    }
                    int sex = Contact.sex(ObjectConverter.parseStringToSexInteger(req.getParameter("sex")));
                    urlBuilder = sex == Contact.UNKNOWN_SEX ? urlBuilder : urlBuilder.append("&sex=" + sex);
                    Date birthdate = ObjectConverter.parseTextToDate(req.getParameter("birthdate"));
                    if (Objects.nonNull(birthdate)) {
                        urlBuilder.append("&birthdate=" + req.getParameter("birthdate"));
                    }
                    String telephone = req.getParameter("telephone");
                    if (Objects.nonNull(telephone) && (length = telephone.length()) > 0
                            && length <= Contact.MAX_TELEPHONE_LENGTH) {
                        urlBuilder.append("&telephone=" + telephone);
                    }
                    temporary = new Contact(contactName, sex, birthdate, telephone);
                    size = size < Page.DEFAULT_SIZE ? Page.DEFAULT_SIZE : size;
                    serial = serial < Page.DEFAULT_SERIAL ? Page.DEFAULT_SERIAL : serial;
                }
            }
            Page page = null;
            HttpSession session = req.getSession();
            if (Objects.isNull(temporary)) {
                temporary = new Contact();
                temporary.setSex(Contact.UNKNOWN_SEX);
            }
            int groupId = ObjectConverter.parseStringToInteger(req.getParameter("group-id"));
            temporary.setGroupId(groupId);
            urlBuilder = groupId > 0 ? urlBuilder.append("&group-id=" + groupId) : urlBuilder;
            int accountId = ObjectConverter.castObjectToInteger(session.getAttribute("account-id"));
            temporary.setAccountId(accountId);
            page = contactDAO.selectByContact(temporary, size, serial);
            req.setAttribute("page", page);
            req.setAttribute("contact", temporary);
            List<Group> groups = groupDAO.select(accountId);
            req.setAttribute("groups", groups);
            req.setAttribute("url", urlBuilder.toString());
            // 转发请求，目标url-pattern为contacts
            pageContext.forward("contacts");
        } catch (SQLException | NamingException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String operate = req.getParameter("operate");
        HttpSession session = req.getSession();
        int accountId = ObjectConverter.castObjectToInteger(session.getAttribute("account-id"));
        try {
            if (Objects.nonNull(operate) && operate.length() > 0) {
                int contactId = ObjectConverter.parseStringToInteger(req.getParameter("contact-id"));
                String contactName = req.getParameter("contact-name");
                int sex = Contact.sex(ObjectConverter.parseStringToSexInteger(req.getParameter("sex")));
                Date birthdate = ObjectConverter.parseTextToDate(req.getParameter("birthdate"));
                String telephone = req.getParameter("telephone");
                int groupId = ObjectConverter.parseStringToInteger(req.getParameter("group-id"));
                switch (operate) {
                case "add-contact":
                    Contact temporary = new Contact(contactName, sex, birthdate, telephone, groupId, accountId);
                    contactDAO.insert(temporary);
                    resp.sendRedirect("contact-handler");
                    break;
                case "edit-contact":
                    if (contactId > 0) {
                        temporary = new Contact();
                        temporary.setContactId(contactId);
                        temporary.setAccountId(accountId);
                        temporary = contactDAO.selectById(temporary);
                        if (Objects.nonNull(temporary)) {
                            req.setAttribute("contact", temporary);
                            List<Group> groups = groupDAO.select(accountId);
                            req.setAttribute("groups", groups);
                            // 转发请求，目标url-pattern为edit-contact
                            pageContext.forward("edit-contact");
                            return;
                        }
                    }
                    resp.sendRedirect("contact-handler");
                    break;
                case "modify-contact":
                    if (contactId > 0) {
                        temporary = new Contact(contactId, contactName, sex, birthdate, telephone, groupId, accountId);
                        contactDAO.updateById(temporary);
                    }
                    resp.sendRedirect("contact-handler");
                    break;
                case "remove-contact":
                    if (contactId > 0) {
                        temporary = new Contact();
                        temporary.setContactId(contactId);
                        temporary.setAccountId(accountId);
                        contactDAO.deleteById(temporary);
                    }
                    resp.sendRedirect("contact-handler");
                    break;
                case "remove-contacts":
                    String[] contactIds = req.getParameterValues("pre-removed-contact-id");
                    if (Objects.nonNull(contactIds) && contactIds.length > 0) {
                        contactDAO.deleteByIds(contactIds, accountId);
                    }
                    resp.sendRedirect("contact-handler");
                    break;
                default:
                    resp.sendRedirect("contact-handler");
                }
            }
        } catch (SQLException | NamingException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        pageContext = JspFactory.getDefaultFactory().getPageContext(this, req, resp, getServletInfo(), true, 0, true);
        super.service(req, resp);
    }

    @Override
    public void init() throws ServletException {
        try {
            conn = ContactsConnection.open();
            groupDAO = new GroupDAOImpl(conn);
            contactDAO = new ContactDAOImpl(conn);
        } catch (NamingException | SQLException e) {
            e.printStackTrace();
        }
        super.init();
    }

    @Override
    public void destroy() {
        try {
            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        super.destroy();
    }
}
